# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: jhkim

import logging
import os
import shutil
import string

import numpy

from coin.database.util.repository_location_resolver import RepositoryLocationResolver


# Turn strange filename into valid one.
def format_filename(s):
  valid_chars = "/-_.() %s%s" % (string.ascii_letters, string.digits)
  filename = ''.join(c for c in s if c in valid_chars)
  filename = filename.replace(' ', '_')
  return filename


class Serializer(object):
  def __init__(self):
    pass

  def __get_cache_path(self, cache_dict, create_dir=False):
    filepath = RepositoryLocationResolver.resolve_daily_feed_file(cache_dict)
    filepath = format_filename(filepath)
    folder_path = RepositoryLocationResolver.resolve_daily_feed_dir(cache_dict)
    if not os.path.isdir(folder_path) and create_dir:
      try:
        os.makedirs(folder_path)
      except OSError:
        if not os.path.isdir(folder_path):
          raise ValueError("Cannot create dir: ", folder_path)
    return filepath

  def serialize(self, cache_dict, data, compress):
    if type(data) is str:
      cache_dict['type'] = 'text'
    elif len(data.shape) == 1:
      cache_dict['type'] = 'vector'
    else:
      cache_dict['type'] = 'matrix'
    cache_path = self.__get_cache_path(cache_dict, create_dir=True)
    logging.info("setting up %s..." % cache_path)
    self.serialize_impl(cache_path, data, compress)
    logging.info("built cache on %s" % cache_path)

  def deserialize(self, cache_dict):
    cache_path = self.__get_cache_path(cache_dict, create_dir=False)
    return self.deserialize_impl(cache_path)

  def write_text_at(self, cache_path, str_value):
    logging.info("setting up %s..." % cache_path)
    with open(cache_path, 'w') as fwrt:
      fwrt.write(str_value)
    logging.info("built cache on %s" % cache_path)

  def write_text(self, cache_dict, str_value, extension=None):
    if extension is None:
      extension = ""
    cache_path = self.__get_cache_path(cache_dict, create_dir=True) + extension
    logging.info("setting up %s..." % cache_path)
    with open(cache_path, 'w') as fwrt:
      fwrt.write(str_value)
    logging.info("built cache on %s" % cache_path)

  def deploy_file(self, cache_dict, filepath, extension=None):
    if extension is None:
      extension = ""
    cache_path = self.__get_cache_path(cache_dict, create_dir=True) + extension
    logging.info("setting up %s..." % cache_path)
    shutil.copyfile(filepath, cache_path)
    logging.info("built cache on %s" % cache_path)


class CsvSerializer(Serializer):
  def __init__(self):
    Serializer.__init__(self)

  def serialize_impl(self, cache_path, data, compress):
    assert not compress
    numpy.savetxt(cache_path + ".csv", data, delimiter=",", fmt="%s")

  def deserialize_impl(self, cache_path):
    return numpy.loadtxt(cache_path)


class TextSerializer(Serializer):
  def __init__(self):
    Serializer.__init__(self)

  def serialize_impl(self, cache_path, data, compress):
    assert not compress
    with open(cache_path + ".txt", "w+") as f:
      f.write(data)

  def deserialize_impl(self, cache_path):
    assert False
    return ""
